package me.zhengjie.spider.manager;

import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.SpiderRunningException;
import me.zhengjie.spider.comic.domain.SpiderComic;
import me.zhengjie.spider.comic.repository.SpiderComicRepository;
import me.zhengjie.spider.comic.service.SpiderComicDetailService;
import me.zhengjie.spider.comic.service.dto.SpiderComicDetailDto;
import me.zhengjie.spider.common.SpiderAttributeBean;
import me.zhengjie.spider.common.SpiderConstant;
import me.zhengjie.spider.domain.comic.ComicBean;
import me.zhengjie.spider.domain.comic.ComicRuleBean;
import me.zhengjie.spider.rule.service.SpiderRuleService;
import me.zhengjie.spider.rule.service.dto.SpiderRuleDto;
import me.zhengjie.spider.rule.service.dto.SpiderRuleQueryCriteria;
import me.zhengjie.spider.util.pipeline.SpiderComicGeneralPipeline;
import me.zhengjie.spider.util.processor.SpiderComicGeneralPageProcessor;
import me.zhengjie.spider.web.domain.SpiderWeb;
import me.zhengjie.spider.web.repository.SpiderWebRepository;
import me.zhengjie.utils.RedisUtils;
import me.zhengjie.utils.SpringContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SpiderComicManager {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private SpiderAsyncManager spiderAsyncManager;
    @Autowired
    private SpiderComicRepository spiderComicRepository;
    @Autowired
    private SpiderRuleService spiderRuleService;
    @Autowired
    private SpiderComicDetailService spiderComicDetailService;
    @Autowired
    private SpiderWebRepository spiderWebRepository;

    public void doSpider(SpiderWeb spiderWeb, SpiderAttributeBean spiderAttributeBean) throws Exception {
        ComicRuleBean comicRuleBean = buildSpiderComicRuleBean(spiderWeb);
        SpiderComicGeneralPageProcessor spiderComicGeneralPageProcessor = SpringContextHolder.getBean(SpiderComicGeneralPageProcessor.class);
        SpiderComicGeneralPipeline spiderComicGeneralPipeline = SpringContextHolder.getBean(SpiderComicGeneralPipeline.class);
        spiderComicGeneralPageProcessor.setRuleBean(comicRuleBean);
        spiderComicGeneralPipeline.setRuleBean(comicRuleBean);

        Spider.create(spiderComicGeneralPageProcessor).addUrl(comicRuleBean.getMainLink()).addPipeline(spiderComicGeneralPipeline).thread(spiderAttributeBean.getThread()).run();
    }

    public void afterDoSpider(SpiderWeb spiderWeb,  SpiderAttributeBean spiderAttributeBean) {
        ComicRuleBean comicRuleBean = buildSpiderComicRuleBean(spiderWeb);
        List<SpiderComic> spiderComicList = spiderComicRepository.findUnSpiderByWebId(spiderWeb.getWebId());
        for (SpiderComic spiderComic : spiderComicList) {
            try {
                ComicBean comicBean = new ComicBean();
                BeanUtils.copyProperties(spiderComic, comicBean);
                spiderAsyncManager.afterComicMath(comicBean, comicRuleBean, spiderAttributeBean);
            } catch (Exception e) {
                throw new SpiderRunningException("爬取明细失败： " + e);
            }
        }
    }

    public void spiderComicContent(SpiderWeb spiderWeb,  SpiderAttributeBean spiderAttributeBean) {
        ComicRuleBean comicRuleBean = buildSpiderComicRuleBean(spiderWeb);
        List<SpiderComicDetailDto> spiderComicDetailDtoList = spiderComicDetailService.findUnSpiderByWebId(spiderWeb.getWebId());
        for (SpiderComicDetailDto spiderComicDetailDto : spiderComicDetailDtoList) {
            try {
                ComicBean comicBean = new ComicBean();
                BeanUtils.copyProperties(spiderComicDetailDto, comicBean);
                spiderAsyncManager.spiderComicContent(comicBean, comicRuleBean, spiderAttributeBean);
            } catch (Exception e) {
                throw new SpiderRunningException("爬取明细失败： " + e);
            }
        }
    }

    public void spiderComicContentByComic(SpiderComic resources,  SpiderAttributeBean spiderAttributeBean) {
        Optional<SpiderWeb> spiderWebOptional = spiderWebRepository.findById(resources.getWebId());
        if (!spiderWebOptional.isPresent()) {
            return;
        }
        ComicRuleBean comicRuleBean = buildSpiderComicRuleBean(spiderWebOptional.get());
        try {
            ComicBean comicBean = new ComicBean();
            BeanUtils.copyProperties(resources, comicBean);
            spiderAsyncManager.spiderComicContent(comicBean, comicRuleBean, spiderAttributeBean);
        } catch (Exception e) {
            throw new SpiderRunningException("爬取明细失败： " + e);
        }
    }

    public void resetRedisCache(Long webId) {
        String redisKey = String.format(SpiderConstant.SPIDER_COMIC_KEY, webId.toString());
        log.info("redisKey:{}", redisKey);
        this.redisUtils.del(redisKey);
        List<String> spiderComicVOList = spiderComicRepository.findHrefByWebId(webId);
        log.info("ID为{}的数据大小{}", webId, spiderComicVOList.size());
        spiderComicVOList.forEach(href -> {
            String item = webId + SpiderConstant.COLON + href;
            if (!this.redisUtils.hHasKey(redisKey, item)) {
                this.redisUtils.hset(redisKey, item, null);
            }
        });
    }

    public ComicRuleBean buildSpiderComicRuleBean(SpiderWeb spiderWeb) {
        SpiderRuleQueryCriteria searchCriteria = new SpiderRuleQueryCriteria();
        searchCriteria.setWebId(spiderWeb.getWebId());
        List<SpiderRuleDto> spiderRuleVOList = spiderRuleService.queryAll(searchCriteria);
        Map<String, String> map = spiderRuleVOList.stream().collect(Collectors.toMap(SpiderRuleDto::getFieldCode, SpiderRuleDto::getRule));
        ComicRuleBean comicRuleBean = new ComicRuleBean();
        comicRuleBean.setAlt(this.getValueByMap(map, SpiderConstant.ALT));
        comicRuleBean.setImg(this.getValueByMap(map, SpiderConstant.IMG));
        comicRuleBean.setHref(this.getValueByMap(map, SpiderConstant.HREF));
        comicRuleBean.setTargetLink(this.getValueByMap(map, SpiderConstant.TARGET_LINK));
        comicRuleBean.setType(this.getValueByMap(map, SpiderConstant.TYPE));
        comicRuleBean.setTag(this.getValueByMap(map, SpiderConstant.TAG));
        comicRuleBean.setDetail(this.getValueByMap(map, SpiderConstant.DETAIL));
        comicRuleBean.setAuthor(this.getValueByMap(map, SpiderConstant.AUTHOR));
        comicRuleBean.setTargetType(this.getValueByMap(map, SpiderConstant.TARGET_TYPE));
        comicRuleBean.setDetailHref(this.getValueByMap(map, SpiderConstant.DETAIL_HREF));
        comicRuleBean.setImgList(this.getValueByMap(map, SpiderConstant.IMG_LIST));
        comicRuleBean.setKeyHasNextPage(this.getValueByMap(map, SpiderConstant.KEY_HAS_NEXT_PAGE));
        comicRuleBean.setKeyHasNextPageRule(this.getValueByMap(map, SpiderConstant.KEY_HAS_NEXT_PAGE_RULE));
        comicRuleBean.setNextPage(this.getValueByMap(map, SpiderConstant.NEXT_PAGE));
        comicRuleBean.setMainLink(spiderWeb.getWebAddress());
        comicRuleBean.setWebId(spiderWeb.getWebId());
        comicRuleBean.setDomain(spiderWeb.getDomain());
        return comicRuleBean;
    }

    public String getValueByMap(Map<String, String> map, String key) {
        if (map.containsKey(key)) {
            return map.get(key);
        }
        return null;
    }
}
